package io.github.wslxm.springbootplus2.file.controller;

import io.github.wslxm.springbootplus2.core.result.Result;
import io.github.wslxm.springbootplus2.core.result.ResultType;
import io.github.wslxm.springbootplus2.file.constant.RenameRuleEnum;
import io.github.wslxm.springbootplus2.file.properties.FileProperties;
import io.github.wslxm.springbootplus2.file.strategy.context.FileChannelContext;
import io.github.wslxm.springbootplus2.file.strategy.service.FileStrategy;
import io.github.wslxm.springbootplus2.file.util.FileDownloadUtil;
import io.github.wslxm.springbootplus2.file.util.FileUploadUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


/**
 * 文件管理
 * <p>
 * consumes = "multipart/*", headers = "content-type=multipart/form-data"
 * </P>
 *
 * @author wangsong
 * @version 1.0.0
 * @email 1720696548@qq.com
 * @date 2018/10/20 21:32
 */
@RestController
@Tag(name = "文件管理")
@RequestMapping("/api/open/file")
public class FileController {

    /**
     * 文件访问器
     */
    @Autowired
    private FileChannelContext fileChannelContext;

    /**
     * 文件上传配置
     */
    @Autowired
    private FileProperties fileProperties;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Value("${spring.application.name:test}")
    private String applicationName;


    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @Operation(summary = "文件上传", description = "上传成功返回完整可访问URL")
    @Parameters({
            @Parameter(name = "resType", description = "返回类型(1- data=url(默认)  2- data=[name:xxx ,url: xxx])", required = false),
            @Parameter(name = "renameRule", description = "文件名称规则： no /time /uuid /snowflake (默认)", required = false)
    })
    public Result<Object> upload(@RequestParam(required = true) MultipartFile file,
                                 @RequestParam(required = false) Integer resType,
                                 @RequestParam(required = false) String renameRule
    ) {
        renameRule = StringUtils.isNotBlank(renameRule) ? renameRule : RenameRuleEnum.SNOWFLAKE.getValue();
        // 获取渠道进行上传
        FileStrategy fileStrategy = fileChannelContext.getChannel(fileProperties.getChannel());
        // 获取文件路径 applicationName / tenantName
        String filePath = FileUploadUtil.getFilePath(request, applicationName);
        // 获取存储名称 (验证文件格式、处理文件名防止重复)
        String fileName = FileUploadUtil.getNewFileName(file.getOriginalFilename(), renameRule);
        String url = null;
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            url = fileStrategy.upload(inputStream, filePath, fileName, renameRule);
            inputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 返回数据处理
        if (resType == null || resType == 1) {
            return Result.success(url, ResultType.FILE_UPLOAD_SUCCESS.getMsg());
        } else {
            Map<String, String> resMap = new HashMap<>(2, 1);
            resMap.put("name", file.getOriginalFilename());
            resMap.put("url", url);
            return Result.success(resMap, ResultType.FILE_UPLOAD_SUCCESS.getMsg());
        }
    }


    @Operation(summary = "下载上传", description = "可以做为文件重命名接口, 也可以做为任意网络文件下载并上传接口")
    @Parameters({
            @Parameter(name = "url", description = "原文件的访问 url", required = true),
            @Parameter(name = "newFileName", description = "上传后的文件的文件名称 (如果有文件后缀需保留文件的后缀名)", required = true),
            @Parameter(name = "url", description = "原文件的访问 url", required = true),
            @Parameter(name = "newFileName", description = "上传后的文件的文件名称 (如果有文件后缀需保留文件的后缀名)", required = true)
    } )
    @RequestMapping(value = "/downloadUpload", method = RequestMethod.PUT)
    public Object downloadUpload(@RequestParam String url, @RequestParam String newFileName) {
        // 获取存储路径
        String filePath = FileUploadUtil.getFilePath(request, applicationName);
        FileStrategy fileStrategy = fileChannelContext.getChannel(fileProperties.getChannel());
        return Result.success(fileStrategy.downloadUpload(url, filePath, newFileName));
    }

    @Operation(summary = "文件删除")
    @Parameter(name = "filePath", description = "文件存储路径 或 文件可访问的URL ", required = true)
    @RequestMapping(value = "/del", method = RequestMethod.DELETE)
    public Object del(@RequestParam String filePath) {
        FileStrategy fileStrategy = fileChannelContext.getChannel(fileProperties.getChannel());
        return Result.success(fileStrategy.del(filePath));
    }

    @Operation(summary ="文件目录删除")
    @Parameter(name = "filePath", description = "文件目录路径", required = true)
    @RequestMapping(value = "/delFolder", method = RequestMethod.DELETE)
    public Object delFolder(@RequestParam String filePath) {
        FileStrategy fileStrategy = fileChannelContext.getChannel(fileProperties.getChannel());
        return Result.success(fileStrategy.delFolder(filePath));
    }

    @Operation(summary ="文件下载--单文件下载")
    @Parameter(name = "filePath", description = "文件可访问的完整URL", required = true)
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public void download(@RequestParam String filePath) {
        FileDownloadUtil.download(filePath, response);
    }


    @Operation(summary ="文件下载--多文件下载 (批量下载-打压缩包)")
    @Parameters({
            @Parameter(name = "filePaths", description = "文件可访问的完整URL,多个逗号分隔", required = true),
            @Parameter(name = "zipName", description = "下载后的文件名", required = true)
    })
    @RequestMapping(value = "/downloadZip", method = RequestMethod.GET)
    public void downloadZip(@RequestParam String filePaths, @RequestParam String zipName) {
        FileDownloadUtil.downloadZip(Arrays.asList(filePaths.split(",")), zipName, response);
    }

}

